#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
#include <string>
#include <algorithm>

#define TERMINATE "DISCONNECT"
#define QUIT "QUIT"
#define SUCCESS "SUCCESS"
#define FAILURE "FAILURE"

#define BUF_SIZE 1024

int setupSocket(char* serverName, unsigned long serverPort) {
	struct sockaddr_in sockadd;
	struct hostent *hp;
	int sd;

	if ((hp = gethostbyname(serverName)) == NULL) {
		perror("gethostbyname");
		return -1;
	}

	sockadd.sin_family = AF_INET;
	sockadd.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
	sockadd.sin_port = htons(serverPort);

	if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		perror("socket");
		return -1;
	}

	if(connect(sd, (struct sockaddr*) &sockadd, sizeof(sockaddr)) == -1) {
		perror("connect");
		return -1;
	}

	return sd;
}

std::string toUpper(const std::string &str) {
	std::string newStr(str);
	std::transform(newStr.begin(), newStr.end(), newStr.begin(), ::toupper);
	return newStr;
}

int main(int argc, char* argv[]) {
	if(argc != 3) {
		fprintf(stderr, "%s <server name> <server port>\n", argv[0]);
		return 1;	
	}

	char* serverName = argv[1];
	unsigned long serverPort = strtol(argv[2], NULL, 10);

	int socket_descriptor = setupSocket(serverName, serverPort);
	if(socket_descriptor < 0) { fprintf(stderr, "could not create socket descriptor\n"); return 1; }

	while(true) {
		char buffer[BUF_SIZE];

		if(fgets(buffer, BUF_SIZE, stdin) == NULL) break;

		std::string command(buffer);
		std::string upperCaseCommand = toUpper(command);

		if(upperCaseCommand.find(QUIT) != std::string::npos) break;

		send(socket_descriptor, buffer, sizeof(buffer), 0);

		if(recv(socket_descriptor, buffer, BUF_SIZE, 0) < 1) {
			fprintf(stderr, "recv error or got no bytes\n");
			break;
		}

		std::string response(buffer);
		std::string upperCaseResponse = toUpper(response);

		if(upperCaseResponse.find(SUCCESS) == std::string::npos) {
			fprintf(stderr, "Got non-success response... exiting...\n");
			break;
		}
	}

	send(socket_descriptor, TERMINATE, sizeof(TERMINATE), 0);

	close(socket_descriptor);

	return 0;
}
